home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / libpcap-0.0.6 / pcap-bpf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-04  |  5.5 KB  |  234 lines

  1. /*
  2.  * Copyright (c) 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static  char rcsid[] =
  23.     "@(#)$Header: pcap-bpf.c,v 1.14 94/06/03 19:58:49 leres Exp $ (LBL)";
  24. #endif
  25.  
  26. #include <stdio.h>
  27. #include <netdb.h>
  28. #include <ctype.h>
  29. #include <signal.h>
  30. #include <errno.h>
  31. #include <sys/param.h>            /* optionally get BSD define */
  32. #include <sys/time.h>
  33. #include <sys/timeb.h>
  34. #include <sys/socket.h>
  35. #include <sys/file.h>
  36. #include <sys/ioctl.h>
  37. #include <net/bpf.h>
  38. #include <net/if.h>
  39. #include <string.h>
  40.  
  41. #include "pcap-int.h"
  42.  
  43. int
  44. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  45. {
  46.     struct bpf_stat s;
  47.  
  48.     if (ioctl(p->fd, BIOCGSTATS, &s) < 0) {
  49.         sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno));
  50.         return (-1);
  51.     }
  52.  
  53.     ps->ps_recv = s.bs_recv;
  54.     ps->ps_drop = s.bs_drop;
  55.     return (0);
  56. }
  57.  
  58. int
  59. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  60. {
  61.     int cc;
  62.     int n = 0;
  63.     register u_char *bp, *ep;
  64.  
  65.  again:
  66.     cc = p->cc;
  67.     if (p->cc == 0) {
  68.         cc = read(p->fd, (char *)p->buffer, p->bufsize);
  69.         if (cc < 0) {
  70.             /* Don't choke when we get ptraced */
  71.             switch (errno) {
  72.  
  73.             case EINTR:
  74.                 goto again;
  75.  
  76.             case EWOULDBLOCK:
  77.                 return (0);
  78. #if defined(sun) && !defined(BSD)
  79.             /*
  80.              * Due to a SunOS bug, after 2^31 bytes, the kernel
  81.              * file offset overflows and read fails with EINVAL.
  82.              * The lseek() to 0 will fix things.
  83.              */
  84.             case EINVAL:
  85.                 if ((long)(tell(p->fd) + p->bufsize) < 0) {
  86.                     (void)lseek(p->fd, 0, 0);
  87.                     goto again;
  88.                 }
  89.                 /* fall through */
  90. #endif
  91.             }
  92.             sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  93.             return (-1);
  94.         }
  95.         bp = p->buffer;
  96.     } else
  97.         bp = p->bp;
  98.  
  99.     /*
  100.      * Loop through each packet.
  101.      */
  102. #define bhp ((struct bpf_hdr *)bp)
  103.     ep = bp + cc;
  104.     while (bp < ep) {
  105.         register int caplen, hdrlen;
  106.         caplen = bhp->bh_caplen;
  107.         hdrlen = bhp->bh_hdrlen;
  108.         /*
  109.          * XXX A bpf_hdr matches a pcap_pkthdr.
  110.          */
  111.         (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
  112.         bp += BPF_WORDALIGN(caplen + hdrlen);
  113.         if (++n >= cnt && cnt > 0) {
  114.             p->bp = bp;
  115.             p->cc = ep - bp;
  116.             return (n);
  117.         }
  118.     }
  119. #undef bhp
  120.     p->cc = 0;
  121.     return (n);
  122. }
  123.  
  124. static inline int
  125. bpf_open(pcap_t *p, char *errbuf)
  126. {
  127.     int fd;
  128.     int n = 0;
  129.     char device[sizeof "/dev/bpf000"];
  130.  
  131.     /*
  132.      * Go through all the minors and find one that isn't in use.
  133.      */
  134.     do {
  135.         (void)sprintf(device, "/dev/bpf%d", n++);
  136.         fd = open(device, O_RDONLY);
  137.     } while (fd < 0 && errno == EBUSY);
  138.  
  139.     /*
  140.      * XXX better message for all minors used
  141.      */
  142.     if (fd < 0)
  143.         sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));
  144.  
  145.     return (fd);
  146. }
  147.  
  148. pcap_t *
  149. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  150. {
  151.     int fd;
  152.     struct ifreq ifr;
  153.     struct bpf_version bv;
  154.     u_int v;
  155.     pcap_t *p;
  156.  
  157.     p = (pcap_t *)malloc(sizeof(*p));
  158.     if (p == NULL) {
  159.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  160.         return (NULL);
  161.     }
  162.     bzero(p, sizeof(*p));
  163.     fd = bpf_open(p, ebuf);
  164.     if (fd < 0)
  165.         goto bad;
  166.  
  167.     p->fd = fd;
  168.     p->snapshot = snaplen;
  169.  
  170.     if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
  171.         sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));
  172.         goto bad;
  173.     }
  174.     if (bv.bv_major != BPF_MAJOR_VERSION ||
  175.         bv.bv_minor < BPF_MINOR_VERSION) {
  176.         sprintf(ebuf, "kernel bpf filter out of date");
  177.         goto bad;
  178.     }
  179.     (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  180.     if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
  181.         sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));
  182.         goto bad;
  183.     }
  184.     /* Get the data link layer type. */
  185.     if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
  186.         sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));
  187.         goto bad;
  188.     }
  189.     p->linktype = v;
  190.  
  191.     /* set timeout */
  192.     if (to_ms != 0) {
  193.         struct timeval to;
  194.         to.tv_sec = to_ms / 1000;
  195.         to.tv_usec = (to_ms * 1000) % 1000000;
  196.         if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
  197.             sprintf(ebuf, "BIOCSRTIMEOUT: %s",
  198.                 pcap_strerror(errno));
  199.             goto bad;
  200.         }
  201.     }
  202.     if (promisc)
  203.         /* set promiscuous mode, okay if it fails */
  204.         (void)ioctl(p->fd, BIOCPROMISC, NULL);
  205.  
  206.     if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
  207.         sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));
  208.         goto bad;
  209.     }
  210.     p->bufsize = v;
  211.     p->buffer = (u_char*)malloc(p->bufsize);
  212.     if (p->buffer == NULL) {
  213.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  214.         goto bad;
  215.     }
  216.  
  217.     return (p);
  218.  bad:
  219.     free(p);
  220.     return (NULL);
  221. }
  222.  
  223. int
  224. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  225. {
  226.     if (p->sf.rfile != NULL)
  227.         p->fcode = *fp;
  228.     else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
  229.         sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno));
  230.         return (-1);
  231.     }
  232.     return (0);
  233. }
  234.